<template>
  <page-container content="高级表单常见于一次性输入和提交大批量数据的场景">
    <a-card class="card" title="仓库管理" :bordered="false">
      <repository-form ref="repository" :show-submit="false" />
    </a-card>
    <a-card class="card" title="任务管理" :bordered="false">
      <task-form ref="task" :show-submit="false" />
    </a-card>

    <!-- table -->
    <a-card>
      <a-table
        :columns="columns"
        :data-source="data"
        :pagination="false"
        :loading="memberLoading"
      >
        <template v-for="(col, i) in ['name', 'workId', 'department']" :slot="col" slot-scope="text, record">
          <a-input
            v-if="record.editable"
            :key="col"
            style="margin: -5px 0"
            :value="text"
            :placeholder="columns[i].title"
            @change="e => handleChange(e.target.value, record.key, col)"
          />
          <template v-else>
            {{ text }}
          </template>
        </template>
        <template slot="operation" slot-scope="text, record">
          <template v-if="record.editable">
            <span v-if="record.isNew">
              <a @click="saveRow(record)">添加</a>
              <a-divider type="vertical" />
              <a-popconfirm title="是否要删除此行？" @confirm="remove(record.key)">
                <a>删除</a>
              </a-popconfirm>
            </span>
            <span v-else>
              <a @click="saveRow(record)">保存</a>
              <a-divider type="vertical" />
              <a @click="cancel(record.key)">取消</a>
            </span>
          </template>
          <span v-else>
            <a @click="toggle(record.key)">编辑</a>
            <a-divider type="vertical" />
            <a-popconfirm title="是否要删除此行？" @confirm="remove(record.key)">
              <a>删除</a>
            </a-popconfirm>
          </span>
        </template>
      </a-table>
      <a-button
        style="width: 100%; margin-top: 16px; margin-bottom: 8px"
        type="dashed"
        icon="plus"
        @click="newMember"
      >
        新增成员
      </a-button>
    </a-card>

    <!-- fixed footer toolbar -->
    <footer-tool-bar :is-mobile="isMobile" :collapsed="sideCollapsed">
      <span class="popover-wrapper">
        <a-popover
          title="表单校验信息"
          overlay-class-name="antd-pro-pages-forms-style-errorPopover"
          trigger="click"
          :get-popup-container="trigger => trigger.parentNode"
        >
          <template slot="content">
            <li
              v-for="item in errors"
              :key="item.key"
              class="antd-pro-pages-forms-style-errorListItem"
              @click="scrollToField(item.key)"
            >
              <a-icon type="cross-circle-o" class="antd-pro-pages-forms-style-errorIcon" />
              <div class="">{{ item.message }}</div>
              <div class="antd-pro-pages-forms-style-errorField">{{ item.fieldLabel }}</div>
            </li>
          </template>
          <span v-if="errors.length > 0" class="antd-pro-pages-forms-style-errorIcon">
            <a-icon type="exclamation-circle" />{{ errors.length }}
          </span>
        </a-popover>
      </span>
      <a-button type="primary" :loading="loading" @click="validate">
        提交
      </a-button>
    </footer-tool-bar>
  </page-container>
</template>

<script>
    import RepositoryForm from './RepositoryForm'
    import TaskForm from './TaskForm'
    import FooterToolBar from '@/components/FooterToolbar'
    import { baseMixin } from '@/store/app-mixin'

    const fieldLabels = {
        name: '仓库名',
        url: '仓库域名',
        owner: '仓库管理员',
        approver: '审批人',
        dateRange: '生效日期',
        type: '仓库类型',
        name2: '任务名',
        url2: '任务描述',
        owner2: '执行人',
        approver2: '责任人',
        dateRange2: '生效日期',
        type2: '任务类型'
    }

    export default {
        name: 'AdvancedForm',
        components: {
            FooterToolBar,
            RepositoryForm,
            TaskForm
        },
        mixins: [baseMixin],
        data() {
            return {
                loading: false,
                memberLoading: false,

                // table
                columns: [
                    {
                        title: '成员姓名',
                        dataIndex: 'name',
                        key: 'name',
                        width: '20%',
                        scopedSlots: { customRender: 'name' }
                    },
                    {
                        title: '工号',
                        dataIndex: 'workId',
                        key: 'workId',
                        width: '20%',
                        scopedSlots: { customRender: 'workId' }
                    },
                    {
                        title: '所属部门',
                        dataIndex: 'department',
                        key: 'department',
                        width: '40%',
                        scopedSlots: { customRender: 'department' }
                    },
                    {
                        title: '操作',
                        key: 'action',
                        scopedSlots: { customRender: 'operation' }
                    }
                ],
                data: [
                    {
                        key: '1',
                        name: '小明',
                        workId: '001',
                        editable: false,
                        department: '行政部'
                    },
                    {
                        key: '2',
                        name: '李莉',
                        workId: '002',
                        editable: false,
                        department: 'IT部'
                    },
                    {
                        key: '3',
                        name: '王小帅',
                        workId: '003',
                        editable: false,
                        department: '财务部'
                    }
                ],

                errors: []
            }
        },
        methods: {
            handleSubmit(e) {
                e.preventDefault()
            },
            newMember() {
                const length = this.data.length
                this.data.push({
                    key: length === 0 ? '1' : (parseInt(this.data[length - 1].key) + 1).toString(),
                    name: '',
                    workId: '',
                    department: '',
                    editable: true,
                    isNew: true
                })
            },
            remove(key) {
                const newData = this.data.filter(item => item.key !== key)
                this.data = newData
            },
            saveRow(record) {
                this.memberLoading = true
                const { key, name, workId, department } = record
                if (!name || !workId || !department) {
                    this.memberLoading = false
                    this.$message.error('请填写完整成员信息。')
                    return
                }
                // 模拟网络请求、卡顿 800ms
                new Promise((resolve) => {
                    setTimeout(() => {
                        resolve({ loop: false })
                    }, 800)
                }).then(() => {
                    const target = this.data.find(item => item.key === key)
                    target.editable = false
                    target.isNew = false
                    this.memberLoading = false
                })
            },
            toggle(key) {
                const target = this.data.find(item => item.key === key)
                target._originalData = { ...target }
                target.editable = !target.editable
            },
            getRowByKey(key, newData) {
                const data = this.data
                return (newData || data).find(item => item.key === key)
            },
            cancel(key) {
                const target = this.data.find(item => item.key === key)
                Object.keys(target).forEach(key => {
                    target[key] = target._originalData[key]
                })
                target._originalData = undefined
            },
            handleChange(value, key, column) {
                const newData = [...this.data]
                const target = newData.find(item => key === item.key)
                if (target) {
                    target[column] = value
                    this.data = newData
                }
            },

            // 最终全页面提交
            validate() {
                const { $refs: { repository, task }, $notification } = this
                const repositoryForm = new Promise((resolve, reject) => {
                    repository.form.validate()
                            .then((values) => resolve(values))
                            .catch((err) => {
                        reject(err)
                    })
                })
                const taskForm = new Promise((resolve, reject) => {
                    task.form.validate()
                            .then((values) => resolve(values))
                            .catch((err) => {
                      reject(err)
                    })
                })

                // clean this.errors
                this.errors = []
                Promise.all([repositoryForm, taskForm]).then(values => {
                    $notification['error']({
                        message: 'Received values of form:',
                        description: JSON.stringify(values)
                    })
                }).catch((err) => {
                    console.error(err)
                    const tmp = { ...err.errorFields }
                    this.errorList(tmp)
                })
            },
            errorList(errors) {
                if (!errors || errors.length === 0) {
                    return
                }
                this.errors = Object.keys(errors)
                    .filter(key => errors[key])
                    .map(key => ({
                        key: key,
                        message: errors[key][0],
                        fieldLabel: fieldLabels[key]
                    }))
            },
            scrollToField(fieldKey) {
                const labelNode = document.querySelector(`label[for="${fieldKey}"]`)
                if (labelNode) {
                    labelNode.scrollIntoView(true)
                }
            }
        }
    }
</script>

<style lang="less" scoped>
    .card {
        margin-bottom: 24px;
    }

    .popover-wrapper {
        /deep/ .antd-pro-pages-forms-style-errorPopover .ant-popover-inner-content {
            min-width: 256px;
            max-height: 290px;
            padding: 0;
            overflow: auto;
        }
    }

    .antd-pro-pages-forms-style-errorIcon {
        user-select: none;
        margin-right: 24px;
        color: #f5222d;
        cursor: pointer;

        i {
            margin-right: 4px;
        }
    }

    .antd-pro-pages-forms-style-errorListItem {
        padding: 8px 16px;
        list-style: none;
        border-bottom: 1px solid #e8e8e8;
        cursor: pointer;
        transition: all .3s;

        &:hover {
            background: #e6f7ff;
        }

        .antd-pro-pages-forms-style-errorIcon {
            float: left;
            margin-top: 4px;
            margin-right: 12px;
            padding-bottom: 22px;
            color: #f5222d;
        }

        .antd-pro-pages-forms-style-errorField {
            margin-top: 2px;
            color: rgba(0, 0, 0, .45);
            font-size: 12px;
        }
    }
</style>
